初めてのPoetry addでAssertionErrorが出たら確認すべきこと
Poetryの操作に慣れていなかったこともあり、セットアップでエラーに遭遇しました。Poetryを触りはじめの頃には恐らくよくあるエラーのはずです。ここでは、発生したエラーとその解決方法について説明します。
発生したエラーについて
Poetryを触りはじめの人なら見覚えがあるかもしれません。
at ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/incompatibility.py:113 in __str__ 109│ ) 110│ 111│ def __str__(self) -> str: 112│ if isinstance(self._cause, DependencyCause): → 113│ assert len(self._terms) == 2 114│ 115│ depender = self._terms[0] 116│ dependee = self._terms[1] 117│ assert depender.is_positive()
ここだけ見ると分かりづらいので詳細まで広げます。
% poetry add openai -vvv Creating new session for pypi.org Source (PyPI): 68 packages found for openai * Using version ^0.27.8 for openai Updating dependencies Resolving dependencies... 1: fact: openai is 0.1.0 1: derived: openai 1: Version solving took 0.001 seconds. 1: Tried 1 solutions. Stack trace: 16 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:327 in run 325│ 326│ try: → 327│ exit_code = self._run(io) 328│ except BrokenPipeError: 329│ # If we are piped to another process, it may close early and send a 15 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/application.py:190 in _run 188│ self._load_plugins(io) 189│ → 190│ exit_code: int = super()._run(io) 191│ return exit_code 192│ 14 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:431 in _run 429│ io.input.interactive(interactive) 430│ → 431│ exit_code = self._run_command(command, io) 432│ self._running_command = None 433│ 13 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:473 in _run_command 471│ 472│ if error is not None: → 473│ raise error 474│ 475│ return terminate_event.exit_code 12 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/application.py:457 in _run_command 455│ 456│ if command_event.command_should_run(): → 457│ exit_code = command.run(io) 458│ else: 459│ exit_code = ConsoleCommandEvent.RETURN_CODE_DISABLED 11 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/commands/base_command.py:119 in run 117│ io.input.validate() 118│ → 119│ status_code = self.execute(io) 120│ 121│ if status_code is None: 10 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/cleo/commands/command.py:62 in execute 60│ 61│ try: → 62│ return self.handle() 63│ except KeyboardInterrupt: 64│ return 1 9 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/console/commands/add.py:262 in handle 260│ self.installer.whitelist([r["name"] for r in requirements]) 261│ → 262│ status = self.installer.run() 263│ 264│ if status == 0 and not self.option("dry-run"): 8 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/installation/installer.py:116 in run 114│ self._execute_operations = False 115│ → 116│ return self._do_install() 117│ 118│ def dry_run(self, dry_run: bool = True) -> Installer: 7 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/installation/installer.py:263 in _do_install 261│ source_root=self._env.path.joinpath("src") 262│ ): → 263│ ops = solver.solve(use_latest=self._whitelist).calculate_operations() 264│ else: 265│ self._io.write_line("Installing dependencies from lock file") 6 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/solver.py:74 in solve 72│ with self._progress(), self._provider.use_latest_for(use_latest or []): 73│ start = time.time() → 74│ packages, depths = self._solve() 75│ end = time.time() 76│ 5 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/puzzle/solver.py:157 in _solve 155│ 156│ try: → 157│ result = resolve_version(self._package, self._provider) 158│ 159│ packages = result.packages 4 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/__init__.py:18 in resolve_version 16│ solver = VersionSolver(root, provider) 17│ → 18│ return solver.solve() 19│ 3 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/version_solver.py:112 in solve 110│ while next is not None: 111│ self._propagate(next) → 112│ next = self._choose_package_version() 113│ 114│ return self._result() 2 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/version_solver.py:432 in _choose_package_version 430│ conflict = False 431│ for incompatibility in self._provider.incompatibilities_for(package): → 432│ self._add_incompatibility(incompatibility) 433│ 434│ # If an incompatibility is already satisfied, then selecting version 1 ~/Library/Application Support/pypoetry/venv/lib/python3.10/site-packages/poetry/mixology/version_solver.py:468 in _add_incompatibility 466│ 467│ def _add_incompatibility(self, incompatibility: Incompatibility) -> None: → 468│ self._log(f"fact: {incompatibility}") 469│ 470│ for term in incompatibility.terms:
後出しになりますが、今回のpyproject.tomlは以下の通り。
[tool.poetry] name = "openai" version = "0.1.0"
パッケージ名とインストールするライブラリ名が同一の場合に衝突した故に起こったエラーでした。これはパッケージ開発用として、自身もインストールされる前提での一面も持つPoetryの特性とも言えそうです。
対策としては2通り。
- pyproject.tomlのname指定を被らないようにする
- pipでインストールする(
poetry run pip install openai
)
Poetryの仕様に沿う場合はname指定を被らないようにするほうがベターだと思われます。
あとがき
pipenvでは何も考えずにプロジェクト名を決めていて、インストールするライブラリ名と被ることも多々ありました。同じノリでPoetryを触るとエラーになる状況をみて、特定用途向けなのだなと理解しました。
Poetry自体触った時間がまだまだ少ないので、実装意図等確認しつつ挑戦することにします。